﻿@page "/system/logs"
@using CleanArchitecture.Blazor.Application.Features.SystemLogs.Caching
@using CleanArchitecture.Blazor.Application.Features.SystemLogs.DTOs
@using CleanArchitecture.Blazor.Application.Features.SystemLogs.Queries.PaginationQuery
@using CleanArchitecture.Blazor.Application.Features.SystemLogs.Specifications
@using CleanArchitecture.Blazor.Server.UI.Components.UtcToLocalTime
@using CleanArchitecture.Blazor.Server.UI.Services.JsInterop
@using CleanArchitecture.Blazor.Server.UI.Pages.SystemManagement.Components
@using CleanArchitecture.Blazor.Application.Features.SystemLogs.Commands.Clear

@attribute [Authorize(Policy = Permissions.Logs.View)]
@inject IStringLocalizer<SystemLogs> L
<PageTitle>@Title</PageTitle>

<LogsLineCharts></LogsLineCharts>
<MudDataGrid T="SystemLogDto"
             ServerData="@(ServerReload)"
             FixedHeader="true"
             FixedFooter="false"
             RowsPerPage="@_defaultPageSize"
             Style="min-height:700px"
             Loading="@_loading"
             ColumnResizeMode="ResizeMode.Column"
             Hover="true" @ref="_table">
    <ToolBarContent>
        <MudStack Row Spacing="0" Class="flex-grow-1" Justify="Justify.SpaceBetween">
            <MudStack Row AlignItems="AlignItems.Start">
                <MudIcon Icon="@Icons.Material.Filled.BarChart" Size="Size.Large" />
                <MudStack Spacing="0">
                    <MudText Typo="Typo.subtitle2" Class="mb-2">@Title</MudText>
                    <MudEnumSelect Style="min-width:120px" TEnum="SystemLogListView" ValueChanged="OnChangedListView" Value="_systemLogsQuery.ListView" Dense="true" Label="@L["List View"]">
                    </MudEnumSelect>
                </MudStack>
            </MudStack>
            <MudStack Spacing="0" AlignItems="AlignItems.End">
                <MudToolBar Dense WrapContent="true" Class="py-1 px-0">
                    <MudButton 
                               OnClick="@(() => OnRefresh())"
                               StartIcon="@Icons.Material.Outlined.Refresh">
                        @ConstantString.Refresh
                    </MudButton>
                    @if (_accessRights.Purge)
                    {
                        <MudButton 
                        Disabled="@(_clearing)"
                        OnClick="@(OnPurge)"
                        StartIcon="@Icons.Material.Outlined.ClearAll">
                            @L["Clear Logs"]
                        </MudButton>
                    }
                </MudToolBar>
                <MudStack Row Spacing="1">
                    <MudEnumSelect TEnum="LogLevel?" Placeholder="@L["Search by level"]" Value="@_systemLogsQuery.Level" Clearable="true" ValueChanged="OnChangedLevel" Style="min-width:120px" FullWidth="true"> </MudEnumSelect>
                    <MudTextField T="string" Style="min-width:120px" ValueChanged="@(OnSearch)" Value="@_systemLogsQuery.Keyword" Placeholder="Search" Adornment="Adornment.End"
                    AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium">
                    </MudTextField>
                </MudStack>
            </MudStack>
        </MudStack>
    </ToolBarContent>
    <Columns>
        <HierarchyColumn T="SystemLogDto" ButtonDisabledFunc="@(x => string.IsNullOrEmpty(x.Message))" />
        <PropertyColumn Style="width:130px" Property="x => x.TimeStamp" Title="@L[_currentDto.GetMemberDescription(x => x.TimeStamp)]">
            <CellTemplate>
                <UtcToLocal UTCDateTime="@context.Item.TimeStamp"></UtcToLocal>
            </CellTemplate>
        </PropertyColumn>
        <PropertyColumn Style="width:120px" Property="x => x.Level" Title="@L[_currentDto.GetMemberDescription(x => x.Level)]">
            <CellTemplate>
                @switch (context.Item.Level)
                {
                    case "Information":
                        <MudChip Color="Color.Info" Size="Size.Small">@context.Item.Level</MudChip>
                        break;
                    case "Warning":
                        <MudChip Color="Color.Warning" Size="Size.Small">@context.Item.Level</MudChip>
                        break;
                    case "Error":
                        <MudChip Color="Color.Error" Size="Size.Small">@context.Item.Level</MudChip>
                        break;
                    case "Critical":
                        <MudChip Color="Color.Error" Size="Size.Small">@context.Item.Level</MudChip>
                        break;
                    case "Trace":
                    case "Debug":
                    default:
                        <MudChip Size="Size.Small">@context.Item.Level</MudChip>
                        break;
                }
            </CellTemplate>
        </PropertyColumn>
        <PropertyColumn Property="x => x.Message" Title="@L[_currentDto.GetMemberDescription(x => x.Message)]" />
        <PropertyColumn Style="width:120px" Property="x => x.UserName" Title="@L[_currentDto.GetMemberDescription(x => x.UserName)]" />
    </Columns>
    <ChildRowContent>
        <MudCard Elevation="0" Class="ma-2">
            <MudCardHeader Class="pb-2">
                <CardHeaderContent>
                    <MudStack Row Spacing="2" AlignItems="AlignItems.Center">
                        <MudIcon Icon="@Icons.Material.Filled.Article" Size="Size.Medium" />
                        <MudText Typo="Typo.h6">@L["Log Details"]</MudText>
                        <MudSpacer />
                        @switch (context.Item.Level)
                        {
                            case "Information":
                                <MudChip Color="Color.Info" Size="Size.Small" Icon="@Icons.Material.Filled.Info">@context.Item.Level</MudChip>
                                break;
                            case "Warning":
                                <MudChip Color="Color.Warning" Size="Size.Small" Icon="@Icons.Material.Filled.Warning">@context.Item.Level</MudChip>
                                break;
                            case "Error":
                                <MudChip Color="Color.Error" Size="Size.Small" Icon="@Icons.Material.Filled.Error">@context.Item.Level</MudChip>
                                break;
                            case "Critical":
                                <MudChip Color="Color.Error" Size="Size.Small" Icon="@Icons.Material.Filled.ErrorOutline">@context.Item.Level</MudChip>
                                break;
                            case "Trace":
                            case "Debug":
                            default:
                                <MudChip Size="Size.Small" Icon="@Icons.Material.Filled.BugReport">@context.Item.Level</MudChip>
                                break;
                        }
                    </MudStack>
                </CardHeaderContent>
            </MudCardHeader>
            <MudCardContent Class="pt-0">
                <MudGrid Spacing="3">
                    <!-- Message Section -->
                    <MudItem xs="12">
                        <MudStack Spacing="1">
                                <MudText Typo="Typo.body2" Style="word-break: break-word;">@context.Item.Message</MudText>
                        </MudStack>
                    </MudItem>

                    <!-- Exception Section -->
                    @if (!string.IsNullOrEmpty(context.Item.Exception))
                    {
                        <MudItem xs="12">
                            <MudStack Spacing="1">
                                <MudStack Row Spacing="1" AlignItems="AlignItems.Center">
                                    <MudIcon Icon="@Icons.Material.Filled.ErrorOutline" Size="Size.Small" Color="Color.Error" />
                                    <MudText Typo="Typo.subtitle2" Color="Color.Error">@L[_currentDto.GetMemberDescription(x => x.Exception)]</MudText>
                                </MudStack>
                                <MudPaper Elevation="1" Class="pa-3" Style="background-color: var(--mud-palette-error-lighten); border-left: 4px solid var(--mud-palette-error);">
                                    <MudText Typo="Typo.body2" Style="word-break: break-word; font-family: monospace;">@context.Item.Exception</MudText>
                                </MudPaper>
                            </MudStack>
                        </MudItem>
                    }

                    <!-- Client Information Section -->
                    <MudItem xs="12" md="6">
                        <MudStack Spacing="2">
                            <MudStack Row Spacing="1" AlignItems="AlignItems.Center">
                                <MudIcon Icon="@Icons.Material.Filled.Computer" Size="Size.Small" Color="Color.Secondary" />
                                <MudText Typo="Typo.subtitle2" Color="Color.Secondary">@L["Client Information"]</MudText>
                            </MudStack>
                            <MudStack Spacing="1" Class="ml-4">
                                <MudStack Row Spacing="1">
                
                                    <MudText Typo="Typo.caption">@L[_currentDto.GetMemberDescription(x => x.ClientIP)]:</MudText>
                                    <MudText Typo="Typo.body2">@context.Item.ClientIP</MudText>
                                </MudStack>
                                <MudStack Row Spacing="1">
                                    <MudText Typo="Typo.caption">@L[_currentDto.GetMemberDescription(x => x.ClientAgent)]:</MudText>
                                    <MudText Typo="Typo.body2" Style="word-break: break-word;">@context.Item.ClientAgent</MudText>
                                </MudStack>
                                
                            </MudStack>
                        </MudStack>
                    </MudItem>

                    <!-- User Information Section -->
                    <MudItem xs="12" md="6">
                        <MudStack Spacing="2">
                            <MudStack Row Spacing="1" AlignItems="AlignItems.Center">
                                <MudIcon Icon="@Icons.Material.Filled.Person" Size="Size.Small" Color="Color.Secondary" />
                                <MudText Typo="Typo.subtitle2" Color="Color.Secondary">@L["User Information"]</MudText>
                            </MudStack>
                            <MudStack Spacing="1" Class="ml-4">
                                <MudStack Row Spacing="1">
                          
                                    <MudText Typo="Typo.caption">@L[_currentDto.GetMemberDescription(x => x.UserName)]:</MudText>
                                    <MudText Typo="Typo.body2">@(!string.IsNullOrEmpty(context.Item.UserName) ? context.Item.UserName : L["Anonymous"])</MudText>
                                </MudStack>
                                <MudStack Row Spacing="1">
                 
                                    <MudText Typo="Typo.caption">@L[_currentDto.GetMemberDescription(x => x.TimeStamp)]:</MudText>
                                    <UtcToLocal UTCDateTime="@context.Item.TimeStamp"></UtcToLocal>
                                </MudStack>
                            </MudStack>
                        </MudStack>
                    </MudItem>
                </MudGrid>
            </MudCardContent>
        </MudCard>
    </ChildRowContent>
    <NoRecordsContent>
        <MudText>@ConstantString.NoRecords</MudText>
    </NoRecordsContent>
    <LoadingContent>
        <MudText>@ConstantString.Loading</MudText>
    </LoadingContent>
    <PagerContent>
        <MudDataGridPager PageSizeOptions="@(new[] { 10, 15, 30, 50, 100, 500, 1000 })" />
    </PagerContent>
</MudDataGrid>


@code
{
    [CascadingParameter] private Task<AuthenticationState> AuthState { get; set; } = default!;
    [CascadingParameter] private UserProfile? UserProfile { get; set; }
    private string Title { get; set; } = "Logs";
    private string _searchString = string.Empty;
    private MudDataGrid<SystemLogDto> _table = default!;
    private readonly SystemLogDto _currentDto = new();
    private readonly int _defaultPageSize = 15;
    private bool _loading;
    private bool _clearing;
    private LogsAccessRights _accessRights = new();

    private SystemLogsWithPaginationQuery _systemLogsQuery { get; } = new();

    protected override async Task OnInitializedAsync()
    {
        Title = L["Logs"];
        _accessRights = await PermissionService.GetAccessRightsAsync<LogsAccessRights>();
    }


    private async Task<GridData<SystemLogDto>> ServerReload(GridState<SystemLogDto> state)
    {
        try
        {
            _loading = true;
            _systemLogsQuery.OrderBy = state.SortDefinitions.FirstOrDefault()?.SortBy ?? "Id";
            _systemLogsQuery.SortDirection = state.SortDefinitions.FirstOrDefault()?.Descending ?? true ? SortDirection.Descending.ToString() : SortDirection.Ascending.ToString();
            _systemLogsQuery.PageNumber = state.Page + 1;
            _systemLogsQuery.PageSize = state.PageSize;
            _systemLogsQuery.CurrentUser = UserProfile;
            var result = await Mediator.Send(_systemLogsQuery).ConfigureAwait(false);

            return new GridData<SystemLogDto> { TotalItems = result.TotalItems, Items = result.Items };
        }
        finally
        {
            _loading = false;
        }
    }

    private async Task OnChangedListView(SystemLogListView listview)
    {
        _systemLogsQuery.ListView = listview;
        await _table.ReloadServerData();
    }

    private async Task OnChangedLevel(LogLevel? level)
    {
        _systemLogsQuery.Level = level;
        await _table.ReloadServerData();
    }

    private async Task OnSearch(string text)
    {
        _systemLogsQuery.Keyword = text;
        await _table.ReloadServerData();
    }

    private async Task OnRefresh()
    {
        _systemLogsQuery.Keyword = string.Empty;
        SystemLogsCacheKey.Refresh();
        await _table.ReloadServerData();
    }

    private async Task OnPurge()
    {
        var contentText = $"{L["Are you sure you want to erase all the logs?"]}";
        var title = $"{L["Erase logs"]}";
        await DialogServiceHelper.ShowConfirmationDialogAsync(title, contentText, async () =>
        {
            _clearing = true;
            try
            {
                var command = new ClearSystemLogsCommand();
                var result = await Mediator.Send(command);
                await _table.ReloadServerData();
                Snackbar.Add(L["Logs have been erased"], Severity.Info);
            }
            finally
            {
                _clearing = false;
            }
        });
    }
}